package net.chengp.esload4j.db.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @author chengp
 * @email E-mail:chengp@chengp.net
 * @version 创建时间：2020年9月12日 下午3:22:32 
 *
 */
@Slf4j
public class BaseDaoImpl implements BaseDao {

	private Connection conn = null;
	private PreparedStatement ps;
	private ResultSet rs;

	public BaseDaoImpl(String id, String driver, String host, String port, String username, String password) {
		this.conn = DBUtils.getConnection(id, driver, host, port, username, password);
	}

	@Override
	public <T> T query(String sql, Object[] params, Class<T> clazz) throws Exception {
		T t = null;
		try {
			ps = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
			int count = ps.getParameterMetaData().getParameterCount();
			if (params != null && params.length > 0) {
				for (int i = 0; i < count; i++) {
					ps.setObject(i + 1, params[i]);
				}
			}
			rs = ps.executeQuery();
			ResultSetMetaData rsMetaData = rs.getMetaData();
			int countMetaData = rsMetaData.getColumnCount();

			if (rs.next()) {
				t = clazz.newInstance();
				for (int i = 0; i < countMetaData; i++) {
					String columnName = rsMetaData.getColumnName(i + 1);
					Object columnValue = rs.getObject(columnName);
					BeanUtils.copyProperty(t, columnName, columnValue);
				}

			}
		} catch (Exception e) {
			log.error("查询数据失败!", e);
			throw e;
		} finally {
			try {
				DBUtils.closeResource(conn, rs, ps);
			} catch (SQLException e) {
				log.error("关闭数据库连接失败!", e);
			}
		}
		return t;
	}

	@Override
	public <T> List<T> queryAll(String sql, Object[] params, Class<T> clazz) throws Exception {
		T t = null;
		List<T> listT = new ArrayList<T>();
		try {
			ps = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
			int count = ps.getParameterMetaData().getParameterCount();
			if (params != null && params.length > 0) {
				for (int i = 0; i < count; i++) {
					ps.setObject(i + 1, params[i]);
				}
			}
			rs = ps.executeQuery();
			ResultSetMetaData rsMetaData = rs.getMetaData();
			int countMetaData = rsMetaData.getColumnCount();
			while (rs.next()) {
				t = clazz.newInstance();
				for (int i = 0; i < countMetaData; i++) {
					String columnName = rsMetaData.getColumnName(i + 1);
					Object columnValue = rs.getObject(columnName);
					BeanUtils.copyProperty(t, columnName, columnValue);
				}
				listT.add(t);
			}
		} catch (Exception e) {
			log.error("查询数据失败!", e);
			throw e;
		} finally {
			try {
				DBUtils.closeResource(conn, rs, ps);
			} catch (SQLException e) {
				log.error("关闭数据库连接失败!", e);
			}
		}
		return listT;
	}

	@Override
	public List<Map<String, Object>> queryAllForMap(String sql, Object[] params) throws Exception {
		List<Map<String, Object>> listT = new ArrayList<Map<String, Object>>();
		try {
			ps = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
			int count = ps.getParameterMetaData().getParameterCount();
			if (params != null && params.length > 0) {
				for (int i = 0; i < count; i++) {
					ps.setObject(i + 1, params[i]);
				}
			}
			rs = ps.executeQuery();
			ResultSetMetaData rsMetaData = rs.getMetaData();
			int countMetaData = rsMetaData.getColumnCount();
			while (rs.next()) {
				Map<String, Object> map = new HashMap<String, Object>();
				for (int i = 0; i < countMetaData; i++) {
					String columnName = rsMetaData.getColumnName(i + 1);
					Object columnValue = rs.getObject(columnName);
					if(columnValue!=null && columnValue instanceof java.sql.Timestamp) {
						java.sql.Timestamp t = (Timestamp) columnValue;
						columnValue = new Date(t.getTime());
					}
					map.put(columnName, columnValue);
				}
				listT.add(map);
			}
		} catch (Exception e) {
			log.error("查询数据失败!", e);
			throw e;
		} finally {
			try {
				DBUtils.closeResource(conn, rs, ps);
			} catch (SQLException e) {
				log.error("关闭数据库连接失败!", e);
			}
		}
		return listT;
	}

	@Override
	public long count(String tableName) throws Exception {
		long result = 0;
		try {
			ps = conn.prepareStatement("select count(1) from "+tableName, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
			rs = ps.executeQuery();
			while (rs.next()) {
				result = rs.getLong(1);
			}
		} catch (Exception e) {
			log.error("查询数据失败!", e);
			throw e;
		} finally {
			try {
				DBUtils.closeResource(conn, rs, ps);
			} catch (SQLException e) {
				log.error("关闭数据库连接失败!", e);
			}
		}
		return result;
	}

}